/*
   Copyright (c) 2019 Shanghai Xuanzi Technology Co. Ltd https://xuanzi.ltd
   XZMindMap is licensed under the Mulan PSL v1.
   You can use this software according to the terms and conditions of the Mulan PSL v1.
   You may obtain a copy of Mulan PSL v1 at:
      http://license.coscl.org.cn/MulanPSL
   THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
   PURPOSE.
   See the Mulan PSL v1 for more details.

*/

package xuanzi.commons.graphics;

import java.util.Stack;

import xuanzi.commons.graphics.Path.CubicTo;
import xuanzi.commons.graphics.Path.LineTo;
import xuanzi.commons.graphics.Path.MoveTo;
import xuanzi.commons.graphics.Path.QuadTo;

/**
 * SVG 文件合成接口
 * @author 彭立铭
 *
 */
public class SVGCanvas implements Canvas{
	
	public static boolean renderImage = false;
	
	boolean noBorder;
	
	float scale = 1f;
	
	float translateX,translateY;

	public static boolean integerNum = true;
	
	public static void setIntegerNum(boolean integerNum) {
		integerNum = integerNum;
	}
	
	public void setRenderImage(boolean renderImage) {
		this.renderImage = renderImage;
	}
	
	StringBuffer buffer = new StringBuffer(
			"<?xml version=\"1.0\" standalone=\"no\"?>\r\n" + 
			"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.0//EN\"\r\n" + 
			"\"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd\">\r\n" + 
			"");
	
 
	
	@Override
	public String toString() { 
		return buffer.append("\n</svg>").toString();
	}
	
	public SVGCanvas() {
		
	}
	
	
	public SVGCanvas(float width, float height) {
	
		buffer.append("\n<?xml-stylesheet type=\"text/css\" href=\"https://jpdaotu.com/versions/static/assets/icons/icons.css\"?>\r\n" + 
				"");
		buffer.append("<svg xmlns=\"http://www.w3.org/2000/svg\" ").append(" height=\"").append(height).append("\" width=\"").append(width).append("\" ").append(" viewBox=\"0 0 ").append(width).append(" ").append(height).append("\">");
	}
	
	public void resize(float width,float height) {
		buffer  = new StringBuffer();
		
		buffer.append("\n<?xml-stylesheet type=\"text/css\" href=\"https://jpdaotu.com/versions/static/assets/icons/icons.css\"?>\r\n" + 
				"");
		buffer.append("<svg xmlns=\"http://www.w3.org/2000/svg\" ").append(" height=\"").append(height).append("\" width=\"").append(width).append("\" ").append(" viewBox=\"0 0 ").append(width).append(" ").append(height).append("\">");

	}
	
	public SVGCanvas(float width, float height,String attr,boolean bound) {
		
		buffer.append("\n<?xml-stylesheet type=\"text/css\" href=\"https://jpdaotu.com/versions/static/assets/icons/icons.css\"?>\r\n" ).append(
				"");
		buffer.append("<svg xmlns=\"http://www.w3.org/2000/svg\" ");
		if(bound)
			buffer.append(" height=\"").append(height).append("\" width=\"").append(width).append("\" ");
		buffer.append(attr).append(" viewBox=\"0 0 ").append(width).append(" ").append(height).append("\">");
	}
	

	public SVGCanvas(float width, float height, String attr) {
		
		buffer.append("\n<?xml-stylesheet type=\"text/css\" href=\"https://jpdaotu.com/versions/static/assets/icons/icons.css\"?>\r\n" ).append(
				"");
		buffer.append("<svg xmlns=\"http://www.w3.org/2000/svg\" ").append(" height=\"").append(height).append("\" width=\"").append(width).append("\" ").append(attr).append(" viewBox=\"0 0 ").append(width).append(" ").append(height).append("\">");
	}
	
	public SVGCanvas addScript(String script){
		buffer.append("\n<script type=\"text/ecmascript\">\r\n" + 
				"   <![CDATA[");
		buffer.append(script);
		buffer.append("]]>\r\n" + 
				"   </script>\n");
		return this;
	}
	
	public SVGCanvas linkScript(String script){
		buffer.append("\n<script href=\""+script+"\" type=\"text/ecmascript\"></script>\n");
		return this;
	}
	
	public SVGCanvas addMeta(String id,String text){
		startTag("g").attr("id", id).text(text).endTag("g");
		return this;
	}

	public SVGCanvas startTag(String tag){
		if(!closeTag)
			buffer.append(">");
		buffer.append("\n<").append(tag);
		closeTag = false;
		return this;
	}
	
	boolean closeTag = true;
	
	public SVGCanvas endTag(String tag) {
		if(!closeTag)
			buffer.append(">");
		buffer.append("</").append(tag).append(">");
		closeTag = true;
		return this;
	}
	
	public SVGCanvas attr(String name,String value) {
		buffer.append(" ").append(name).append("=\"").append(value).append("\"");
		return this;
	}
	
	public SVGCanvas attr(String name,float value) { 
		buffer.append(" ").append(name).append("=\"").append(integerNum?(int)value:value).append("\"");
		return this;
	}
	
	public SVGCanvas attr(String name,int value) {
		buffer.append(" ").append(name).append("=\"").append(value).append("\"");
		return this;
	}
	
	public SVGCanvas text(String text) {
		buffer.append("><![CDATA[").append(text).append("]]>");
		closeTag = true;
		return this;
	}
    
		public void drawRect(BoxF bound,Paint paint) {
			startTag("rect").attr("x", bound.left).attr("y", bound.top).attr("height", bound.height()).attr("width", bound.width())
			;
			applyAttrs(paint); 
			endTag("rect");
		 
		}

		private void applyAttrs(Paint paint) {
			if(paint.borderSize>0)
				attr("stroke-width",paint.borderSize);
			if(paint.fill) {
				attr("fill",Color.int2RGBA(paint.fillColor)).attr("stroke", "none");
			}else {
				attr("fill", "none").attr("stroke", Color.int2RGBA(paint.borderColor));
			}
			 
		}
 
	@Override
	public void translate(float x, float y) { 
	 
		startTag("g").attr("transform", "translate("+x+","+y+")");
	}
	
	class State{
		float translateX,translateY;
		float scale;
	}
	
	Stack<State> stateList = new Stack<State>();
	
	@Override
	public void save() { 
		
	 
		State state = new State();
		state.translateX = translateX;
		state.translateY = translateY;
		state.scale = scale;
		stateList.push(state);
		 
		
	}
	
	
	@Override
	public void drawImage(Image path, float dx, float dy) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void drawImage(Image path, float sx, float sy, float sWidth, float sHeight) {
		// TODO Auto-generated method stub
		
	}
	
	@Override
	public void drawImage(Image path, float sx, float sy, float sWidth, float sHeight, float dx, float dy, float dWidth,
			float dHeight) {
		// TODO Auto-generated method stub
		
	}
	
	
	@Override
	public void restore() {
		 
		if(stateList.size()>0) {
			State state = stateList.pop();
			if(state!=null) {
				endTag("g");
				translateX = state.translateX;
				translateY = state.translateY;
				scale = state.scale;
			}
		}
	 
	}
	
	private int color;
  

	private boolean intColor;
	
	public void setIntColor(boolean intColor) {
		this.intColor = intColor;
	}

 
	
	@Override
	public void drawRect(BoxF bound, float rad, Paint paint) {
		startTag("rect").attr("rx", rad).attr("ry", rad).attr("x", bound.left).attr("y", bound.top).attr("height", bound.height()).attr("width", bound.width())
		;
		applyAttrs(paint); 
		endTag("rect");
	}
	
	@Override
	public float textWidth(String text, boolean mline,Paint paint) { 
		if(text==null)
			return 0;
		return text.length()*(paint.textSize*1.08f);
	}

	@Override
	public void drawText(String text, float x, float y, Paint paint) { 
		float w = textWidth(text,false,paint); 
		float cx = x;// x+w/4;
		if(paint.textAlign==0) {
			cx = x - w*0.45f;
		}else if(paint.textAlign == 1) {
			cx = x - w;
		}
			
		startTag("text");
		attr("font-size", paint.textSize);
		attr("x", cx);
		attr("y", y+paint.textSize/2);
		/*
		if(paint.fill) {
			attr("fill",Color.int2RGBA(paint.textColor)).attr("stroke", "none");
		}else {
			attr("fill", "none").attr("stroke", Color.int2RGBA(paint.textColor));
		}*/
		
		applyAttrs(paint);
		text(text);
		endTag("text");
	}

	@Override
	public void drawOval(BoxF bound, Paint paint) {
		
		startTag("ellipse");
		attr("cx", bound.centerX());
		attr("cy", bound.centerY());
		attr("rx", bound.width()/2);
		attr("ry", bound.height()/2);
		applyAttrs(paint);
		
		endTag("ellipse");
	}

	@Override
	public void drawLine(float x, float y, float tx, float ty,Paint paint) {
		// TODO Auto-generated method stub
		startTag("line").attr("x1", x).attr("y1",  y).attr("x2",  tx).attr("y2",  ty);
		applyAttrs(paint); 
		endTag("line");
	}
	
	StringBuffer pathBuffer;
	
	@Override
	public void drawPath(Path path, Paint paint) { 
		pathBuffer = new StringBuffer();
		startTag("path");
		applyAttrs(paint);  
		for(Path.Shape p:path.shapes) {
			if(p instanceof Path.Close) {
				closePath();
			}else if(p instanceof Path.MoveTo) {
				MoveTo mt = (MoveTo) p;
				 moveTo(mt.x, mt.y);
			}else if(p instanceof Path.LineTo) {
				LineTo mt = (LineTo) p;
				 lineTo(mt.x, mt.y);
			}else if(p instanceof Path.QuadTo) {
				QuadTo mt = (QuadTo) p;
				 quadTo(mt.x1, mt.y1, mt.x2, mt.y2);
			}else if(p instanceof Path.CubicTo) {
				CubicTo mt = (CubicTo) p;
				 cubicTo(mt.x1, mt.y1, mt.x2, mt.y2, mt.x3, mt.y3);
			}
		}
		attr("d", pathBuffer.toString());
		endTag("path");
	}
	
	  
	public void closePath() {
		pathBuffer.append("Z");
	}
 
	public void cubicTo(float x1, float y1, float x2, float y2, float x3, float y3) {
		pathBuffer.append("C")
		.append(SVGCanvas.integerNum?(int)x1:x1)
		.append(" ").append( SVGCanvas.integerNum?(int)y1:y1)
		.append(" ").append( SVGCanvas.integerNum?(int)x2:x2)
		.append(" ").append( SVGCanvas.integerNum?(int)y2:y2)
		.append(" ").append( SVGCanvas.integerNum?(int)x3:x3)
		.append(" ").append( SVGCanvas.integerNum?(int)y3:y3);
	}

	public void moveTo(float x, float y) {
		//context2d.moveTo(x, y);
		pathBuffer.append("M")
			.append( SVGCanvas.integerNum?(int)x:x).append(" ")
			.append( SVGCanvas.integerNum?(int)y:y).append(" ");
	}

	public void lineTo(float x, float y) {
		pathBuffer.append("L")
			.append( SVGCanvas.integerNum?(int)x:x).append(" ").append( SVGCanvas.integerNum?(int)y:y).append(" ");
	}

	public void quadTo(float x, float y, float x2, float y2) {
		pathBuffer.append("Q")
			.append( SVGCanvas.integerNum?(int)x:x)
			.append(" ").append(SVGCanvas.integerNum?(int)y: y)
			.append(" ").append( SVGCanvas.integerNum?(int)x2:x2)
			.append(" ").append( SVGCanvas.integerNum?(int)y2:y2).append(" ");
		
	}
	
 
 
}
